import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.management.Notification;

import org.apache.lucene.search.function.ReverseOrdFieldSource;

import controllers.Application;
import models.ActionItem;
import models.Comment;
import models.EEntity;
import models.Idea;
import models.OrderIdeaByCreatorContribution;
import models.OrderObjectsByCount;
import models.Organization;
import models.Tag;
import models.ObjectWithCount;
import models.Topic;
import models.User;
import play.jobs.Every;
import play.jobs.Job;
import play.jobs.On;

/**
 * ScheduledJobs.java Purpose: Scheduled Job
 * 
 * @version 1.0 4/25/2011
 * @author Ahmed Mahmoud
 */

/* Fire at Sat & Tue of each week */
@On("0 0 0 1/2 * ?")
public class ScheduledJobs extends Job {
	/**
	 * the method runs every 2 days at midnight to check on active inactive
	 * topics, sends and adds notifications to the organization leads of the
	 * organizations discussing these topics.
	 */
	public void checkForInActiveTopics() {
		ArrayList<Topic> topics = Application.getInactiveTopics();
		ArrayList<User> users = new ArrayList<User>();
		for (Topic topic : topics) {
			User user = null;
			// Not Implemented yet.
			user = topic.entity.organization.getOrganizationLead();
			if (!users.contains(user)) {
				users.add(user);
			}
		}
		String msg = "LOL you have topics(s)" + " that are inactive for a week";
		String subject = "Notification About inActive Topics";
		Application.sendMail(msg, subject, users);

		for (Topic inactiveTopic : topics) {
			ArrayList<User> temp = new ArrayList<User>();
			temp.add(inactiveTopic.entity.organization.getOrganizationLead());
			new models.Notification("Inactive Topics", inactiveTopic.id, 11,
					temp.get(0), temp).save();
			temp.get(0).merge()._save();
		}

	}

	/**
	 * the method runs every 2 days at midnight to check on inactive ideas, send
	 * and add notifications to the authors of these Ideas
	 */
	public void CheckForInactiveIdeas() {
		ArrayList<Idea> inactiveIdeas = Application.getInactiveIdeas();
		ArrayList<User> users = new ArrayList<User>();
		for (Idea inactiveIdea : inactiveIdeas) {
			if (!users.contains(inactiveIdea.creator)) {
				users.add(inactiveIdea.creator);
			}
		}
		String msg = "LOL you have idea(s)" + " that are inactive for a week";
		String subject = "Notification About inActive Idea";
		Application.sendMail(msg, subject, users);

		for (Idea inactiveIdea : inactiveIdeas) {
			ArrayList<User> notifiedUsers = new ArrayList<User>();
			notifiedUsers.add(inactiveIdea.creator);
			new models.Notification("Inactive Idea", inactiveIdea.id, 4,
					inactiveIdea.creator, notifiedUsers).save();
			inactiveIdea.creator.merge()._save();
		}
	}

	/**
	 * Gives the Organizations indexes representing its turn in a list of
	 * Popular Organization it sums all the number of tpics ideas, and comments
	 * in certaing orgnization and this number will be its index;
	 */
	public void setPopularOrganizations() {
		List<Organization> organizations = Organization.findAll();
		for (Organization organization : organizations) {
			organization.howMuchPopular = organization.numberOfView;
			for (EEntity entity : organization.entities) {
				organization.howMuchPopular += entity.topics.size();
				for (Topic topic : entity.topics) {
					organization.howMuchPopular += topic.ideas.size();
				}
			}
			organization.merge()._save();
		}
	}

	/**
	 * Gives the Topic indexes representing its turn in a list of Popular Topics
	 * it sums all the number of ideas, and comments in certain Topic and this
	 * number will be its index;
	 */

	public void setpopularTopicsInOrganizations() {
		List<Organization> organizations = Organization.findAll();
		for (Organization organization : organizations) {
			List<Topic> topics = Topic.find(
					"select t from Topic " + "where t.entity."
							+ "organization = ?", organization).fetch();
			for (Topic topic : topics) {
				topic.howMuchPopular = topic.numberOfView + topic.ideas.size();
				for (Idea idea : topic.ideas) {
					topic.howMuchPopular += idea.comments.size();
				}
				topic.merge()._save();
			}

		}
	}

	/**
	 * sets the featuredIdeas list in the Organization to be the list of ideas
	 * whose authors have highest Community Contribution.
	 */
	public void setFeaturedIdeasInOrganization() {
		List<Organization> allOrganizations = Organization.findAll();
		ArrayList<Idea> featuredIdeas = new ArrayList<Idea>();
		for (Organization organization : allOrganizations) {
			List<Idea> organizatonIdeas = new ArrayList<Idea>();
			for (EEntity entity : organization.entities) {
				for (Topic topic : entity.topics) {
					organizatonIdeas.addAll(topic.ideas);
				}
			}
			Comparator<Idea> reversedOrder = Collections
					.reverseOrder(new OrderIdeaByCreatorContribution());
			Collections.sort(organizatonIdeas, reversedOrder);
			List<Idea> ideas = organizatonIdeas.subList(0, (organizatonIdeas
					.size() > 10 ? 10 : organizatonIdeas.size() - 1));
			featuredIdeas.addAll(ideas);
			organization.organizationFeaturedIdeas = featuredIdeas;
			organization.merge()._save();
		}
	}

	public void setFeaturedTopicsAndIdeasForUsers() {
		List<User> allUsers = User.findAll();
		for (User user : allUsers) {
			/*************************************************************/
			List<ObjectWithCount> topTagsWithCount = user.getTopTags();

			List<Tag> topTags = new ArrayList<Tag>();
			for (ObjectWithCount<String> tagWithCount : topTagsWithCount) {
				topTags.add((Tag) Tag.find("name", tagWithCount.Object).first());
			}
			topTags.subList(0, topTags.size() / 2 + 1);
			/*************************************************************/
			List<Topic> allTopics = Topic.findAll();
			ArrayList<ObjectWithCount<Topic>> topicsWithCount = new ArrayList<ObjectWithCount<Topic>>();
			for (Topic topic : allTopics) {
				int i = 0;
				for (Tag tag : topic.tags) {
					if (topTags.contains(tag)) {
						i += topTags.size() - topTags.indexOf(tag);
					}
				}
				topicsWithCount.add(new ObjectWithCount<Topic>(topic, i));
			}
			Collections.sort(topicsWithCount, new OrderObjectsByCount());
			List<Topic> featuredTopics = new ArrayList<Topic>();
			for (ObjectWithCount<Topic> topicWithcount : topicsWithCount) {
				featuredTopics.add(topicWithcount.Object);
			}
			user.featuredTopics = featuredTopics;
			/****************************************************************/
			List<Idea> allIdeas = Idea.findAll();
			ArrayList<ObjectWithCount<Idea>> ideasWithCount = new ArrayList<ObjectWithCount<Idea>>();
			for (Idea idea : allIdeas) {
				int i = 0;
				for (Tag tag : idea.tags) {
					if (topTags.contains(tag)) {
						i += topTags.size() - topTags.indexOf(tag);
					}
				}
				ideasWithCount.add(new ObjectWithCount<Idea>(idea, i));
			}
			Collections.sort(ideasWithCount, new OrderObjectsByCount());
			List<Idea> featuredIdeas = new ArrayList<Idea>();
			for (ObjectWithCount<Idea> ideaWithcount : ideasWithCount) {
				featuredIdeas.add(ideaWithcount.Object);
			}
			user.featuredIdeas = featuredIdeas;
			user.merge()._save();
		}

	}

}